home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Nebula 2
/
Nebula Two.iso
/
SourceCode
/
Database
/
RecordManager
/
Controller.m
< prev
next >
Wrap
Text File
|
1993-05-04
|
7KB
|
295 lines
/* Controller.m:
* You may freely copy, distribute, and reuse the code in this example.
* NeXT disclaims any warranty of any kind, expressed or implied, as to its
* fitness for any particular use.
*
*
*/
#import <pwd.h>
#import <sys/param.h>
#import <indexing/IXRecordManager.h>
#import <indexing/IXPostingList.h>
#import <indexing/protocols.h>
#import <btree/protocols.h>
#import <btree/IXPostingSet.h>
#import <store/IXStoreFile.h>
#import <architecture/byte_order.h>
#import "Controller.h"
#import "DataRecord.h"
#define STRINGLEN(A) (strlen((A)) + 1)
@implementation Controller
- free
{
[recMan free];
if (postingList != nil)
postingList = [[postingList freeObjects] free];
return [super free];
}
/*
* Commits any pending transactions to disk.
*/
- commit
{
[[recMan store] commitTransaction];
return self;
}
/* TARGET ACTION METHODS */
- clear:sender
{
[idField setStringValue:""];
[dataForm setStringValue:"" at:0];
[dataForm setStringValue:"" at:1];
return self;
}
/*
* Adds a new record to the database. A DataRecord is created and initialized
* from the fields in the dataForm.
*/
- addARecord:sender
{
id newRec;
const char *stringInput;
const char *numberInput;
/* create and setup the new record */
/* We don't allow empty input, since those records can't be retrieved
* later on
*/
stringInput = (const char *)[dataForm stringValueAt:0];
numberInput = (const char *)[dataForm stringValueAt:1];
if ( (strcmp(stringInput, "") == 0) || (strcmp(numberInput, "") == 0) ){
NXRunAlertPanel("Error", "You must supply a string.", NULL, NULL, NULL);
return self;
}
newRec = [[DataRecord alloc] init];
[newRec setAString:[dataForm stringValueAt:0]];
[newRec setAnInt:[dataForm intValueAt:1]];
/* add it in */
[idField setIntValue:[recMan addRecord:newRec]];
[newRec free];
[self commit];
[dataForm selectTextAt:0];
return self;
}
/*
* Delete the current record from the database.
*/
- deleteRecord:sender
{
id retval;
unsigned int aHandle;
aHandle = (unsigned)[idField intValue];
retval = [recMan removeRecord:aHandle];
if(retval != nil)
{
[self clear:self];
[self commit];
}
return self;
}
/*
* Changes the data fields of the current record. This is done by creating a
* new record and replacing the existing one with the new one.
*/
- editRecord:sender
{
id newRec;
/* create and setup the replacement record */
newRec = [[DataRecord alloc] init];
[newRec setAString:[dataForm stringValueAt:0]];
[newRec setAnInt:[dataForm intValueAt:1]];
/* replace it */
[recMan replaceRecord:[idField intValue] with:newRec];
[newRec free];
[self commit];
return self;
}
/*
* Searches for records in the database.
* If the allSwitch is set, we simply pull all records from the record manager.
* If the allSwitch is not set, we search on each attribute 'anding' the
* results as we go along.
*/
- search:sender
{
id cur;
char *searchString;
IXPostingSet *postingSet;
unsigned int intfld;
if (postingList != nil)
postingList = [[postingList freeObjects] free];
if(![allSwitch state])
{
postingSet = [[IXPostingSet alloc] init];
/* first search the string attribute */
searchString = (char *)[searchForm stringValueAt:0];
if(searchString && *searchString != '\0')
{
cur = [recMan cursorForAttributeNamed:DRASTRINGNAME];
if([cur setKey:searchString andLength:STRINGLEN(searchString)])
[postingSet formUnionWithPostingsIn:cur];
[cur free]; // must free cursor to avoid leaking.
}
/* now search the integer attribute */
searchString = (char *)[searchForm stringValueAt:1];
if(searchString && *searchString != '\0')
{
cur = [recMan cursorForAttributeNamed:DRANINTNAME];
intfld = atoi(searchString);
/* accumulate results in the IXPostingSet.
Do a logical AND if there were string matches above,
otherwise, just do a logical OR.
*/
/* Swap if this is a little-endian machine. */
if ( NXHostByteOrder() == NX_LittleEndian )
intfld = NXSwapInt(intfld);
if([cur setKey:(void *)&intfld andLength:sizeof(unsigned int)])
{
if([postingSet count] > 0)
[postingSet formIntersectionWithPostingsIn:cur];
else
[postingSet formUnionWithPostingsIn:cur];
}
[cur free]; // must free cursor to avoid leaking.
}
[searchForm selectTextAt:0];
postingList = [[IXPostingList alloc] initWithSource:recMan andPostingsIn:postingSet];
[postingSet free];
} else
postingList = [recMan recordsForClass:[DataRecord class]];
[recBrowser loadColumnZero];
return self;
}
- browserHit:sender
/*
* Responds to the user selecting a handle in the browser by retrieving
* the corresponding record and displaying its values in the dataForm.
*/
{
int col = [recBrowser selectedColumn];
id dr, matrix = [recBrowser matrixInColumn:col];
unsigned int handle;
handle = [[matrix selectedCell] intValue];
[idField setIntValue:handle];
if((dr = [recMan readRecord:handle fromZone:[self zone]]) == nil)
{
NXRunAlertPanel("Error", "Cannot read record", NULL, NULL, NULL);
[self clear:self];
} else
{
[dataForm setStringValue:[dr aString] at:0];
[dataForm setIntValue:[dr anInt] at:1];
[dr free];
}
return self;
}
/* NXBROWSER DELEGATE METHODS */
- (int)browser:sender fillMatrix:matrix inColumn:(int)col
{
id cell;
int i, rows = 0;
if (postingList != nil)
rows = [postingList count];
for(i = 0; i < rows; i++)
{
[matrix insertRowAt:i];
cell = [matrix cellAt:i :0];
[cell setIntValue:[postingList handleOfObjectAt:i]];
[cell setLoaded:YES];
[cell setLeaf:YES];
}
return rows;
}
/* APPLICATION DELEGATE METHODS */
- appDidInit:sender
{
struct passwd *pw;
char path[MAXPATHLEN];
pw = getpwuid(getuid());
sprintf(path, "%s/%s", pw->pw_dir, DBFILENAME);
fprintf(stderr, "path %s\n", path);
[recBrowser acceptArrowKeys:YES andSendActionMessages:YES];
if(access(path, F_OK) == -1)
{
/* create new database */
recMan = [[IXRecordManager alloc] initWithName:DBNAME inFile:path];
if (recMan == nil)
{
NXRunAlertPanel("Error", "Cannot create database.", NULL, NULL, NULL);
[NXApp terminate:self];
}
[recMan addAttributeNamed:DRASTRINGNAME forSelector:@selector(aString)];
[recMan setComparator:&IXCompareMonocaseStrings andContext:NULL
forAttributeNamed:DRASTRINGNAME];
[recMan addAttributeNamed:DRANINTNAME forSelector:@selector(anInt)];
[recMan setComparator:&IXCompareLongs andContext:NULL
forAttributeNamed:DRANINTNAME];
} else
{
/* open existing database */
recMan = [[IXRecordManager alloc] initFromName:DBNAME inFile:path forWriting:YES];
if (recMan == nil)
{
NXRunAlertPanel("Error", "Cannot open database.", NULL, NULL, NULL);
[NXApp terminate:self];
}
}
[[recMan store] startTransaction];
[[recMan store] commitTransaction]; // don't want to leave a transaction pending
return self;
}
-appWillTerminate:sender
{
[self commit];
return self;
}
@end